﻿namespace UnityEditor
{
    using Mono.Cecil;
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;

    public class AssemblyTypeInfoGenerator
    {
        private AssemblyDefinition assembly_;
        private List<ClassInfo> classes_ = new List<ClassInfo>();

        public AssemblyTypeInfoGenerator(string assembly)
        {
            this.assembly_ = AssemblyDefinition.ReadAssembly(assembly);
        }

        public void gatherClassInfo()
        {
            foreach (ModuleDefinition definition in this.assembly_.Modules)
            {
                foreach (TypeDefinition definition2 in definition.Types)
                {
                    if (definition2.Name != "<Module>")
                    {
                        ClassInfo item = new ClassInfo {
                            name = this.GetFullTypeName(definition2),
                            fields = this.getFields(definition2)
                        };
                        this.classes_.Add(item);
                    }
                }
            }
        }

        private FieldInfo[] getFields(TypeDefinition type)
        {
            List<FieldInfo> list = new List<FieldInfo>();
            foreach (TypeDefinition definition in type.NestedTypes)
            {
                ClassInfo item = new ClassInfo {
                    name = this.GetFullTypeName(definition),
                    fields = this.getFields(definition)
                };
                this.classes_.Add(item);
            }
            foreach (FieldDefinition definition2 in type.Fields)
            {
                if ((definition2.IsStatic || definition2.IsInitOnly) || (((ushort) (definition2.Attributes & FieldAttributes.NotSerialized)) != 0))
                {
                    continue;
                }
                bool flag = false;
                foreach (CustomAttribute attribute in definition2.CustomAttributes)
                {
                    if (attribute.AttributeType.Name.CompareTo("SerializeField") == 0)
                    {
                        flag = true;
                        break;
                    }
                }
                if (definition2.IsPublic || flag)
                {
                    FieldInfo info2 = new FieldInfo {
                        name = definition2.Name,
                        type = this.GetFullTypeName(definition2.FieldType)
                    };
                    list.Add(info2);
                }
            }
            return list.ToArray();
        }

        private string GetFullTypeName(TypeReference type)
        {
            string fullName = type.FullName;
            while (true)
            {
                int index = fullName.IndexOf('`');
                if (index == -1)
                {
                    return fullName.Replace('/', '.');
                }
                int num2 = index + 1;
                while (num2 < fullName.Length)
                {
                    if ((fullName[num2] < '0') || (fullName[num2] > '9'))
                    {
                        break;
                    }
                    num2++;
                }
                fullName = fullName.Remove(index, num2 - index);
            }
        }

        public ClassInfo[] ClassInfoArray
        {
            get
            {
                return this.classes_.ToArray();
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct ClassInfo
        {
            public string name;
            public AssemblyTypeInfoGenerator.FieldInfo[] fields;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct FieldInfo
        {
            public string name;
            public string type;
        }
    }
}

